//
//  MockProxyEntity.m
//  Oos4ios
//
//  Created by Pablo Gonzalez on 3/1/11.
//  Copyright 2011 11870.com. All rights reserved.
//

#import "ObjectProxy.h"
#import "StringUtils.h"
#import "NSStringUtils.h"

@implementation ObjectProxy

@synthesize internalData = mInternalData;

+ (ObjectProxy *) proxy
{
	return [[[ObjectProxy alloc] init] autorelease];
}

+ (ObjectProxy *) proxyWithArray:(NSArray *)params
{
	return [[[ObjectProxy alloc] initWithArray:params] autorelease];
}

- (ObjectProxy *) initWithArray:(NSArray *)params
{
	self = [self init];
	if(self && params) {
		for (int i = 0; i < [params count]; i += 2) {
			SEL selector = NSSelectorFromString([params objectAtIndex:i]);
			id object = [params objectAtIndex: i+1];
			if(selector && object) {
				[self performSelector:selector withObject:object];
			}
		}
	}
	return self;
}

- (ObjectProxy *) init
{
	self = [super init];
	if (self) {
		self.internalData = [NSMutableDictionary dictionary];
	}
	return self;
}

// Determine if we can handle the unknown selector sel
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
	NSString *methodName = NSStringFromSelector(sel);
	NSArray *components = [methodName componentsSeparatedByString:@":"];
	methodName = [components objectAtIndex:0];
	int	parameterCount = [components count]-1;
	
	// Zero argument, forward to valueForKey:
	if (parameterCount == 0) {
		return [[self internalData] methodSignatureForSelector:
                @selector(valueForKey:)];
	}

	if (parameterCount == 1) {
		if ([methodName hasPrefix:@"set"]) {
			return [[self internalData] methodSignatureForSelector:
                    @selector(setValue:forKey:)];
		} else if ([methodName hasPrefix:@"add"]) {
			return [super methodSignatureForSelector:
                    @selector(addValue:forKey:)];
		} else if ([methodName hasPrefix:@"remove"]) {
			return [super methodSignatureForSelector:
                    @selector(removeValue:forKey:)];
		}
	}
	// Discard the call
	return [super methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation
{
	NSString *methodName = NSStringFromSelector([invocation selector]);
	NSArray *components = [methodName componentsSeparatedByString:@":"];
	methodName = [components objectAtIndex:0];
	int	parameterCount = [components count]-1;
	
	id value = nil;
	methodName = [methodName lowercaseString];
	
	// Forwarding to getter
	if (parameterCount == 0)
	{
		if ([methodName hasSuffix:@"url"]) {
			methodName = [methodName stringByAppendingString: @"string"];
			value = [NSURL URLWithString:[mInternalData valueForKey:methodName]];
		} 
		if (value == nil){
			value = [mInternalData valueForKey:methodName];
		}
		[invocation setReturnValue:&value];
	}
	// Forwarding to setter, adder and remover
	if (parameterCount == 1)
	{
		[invocation getArgument:&value atIndex:2];
		if ([methodName hasPrefix:@"set"]) {
            methodName = [NSStringUtils removePrefix:@"set" fromString: methodName];
			[self setValue:value forKey:methodName];
		} else if ([methodName hasPrefix:@"add"]) {
			methodName = [NSStringUtils removePrefix:@"add" fromString:methodName];
            methodName = [NSStringUtils pluralOf:methodName];
			[self addValue:value forKey:methodName];
		} else if ([methodName hasPrefix:@"remove"]) {
			methodName = [NSStringUtils removePrefix:@"remove" fromString:methodName];
            methodName = [NSStringUtils pluralOf: methodName];
			[self addValue:value forKey:methodName];
		}
	}
	
}

- (void) setValue:(id)value forKey:(NSString *)key
{
	// Handle urls
	if ([value isKindOfClass:[NSURL class]]) {
		value = [(NSURL *)value absoluteString];
		key = [key stringByAppendingString:@"string"];
	}
	[mInternalData setValue:value forKey:key];
}

- (void) addValue: (id) value forKey: (NSString *) key
{
	id data = [mInternalData objectForKey:key];
	NSMutableArray *array;
	if(data && [data isKindOfClass: [NSArray class]]) {
		array = (NSMutableArray *) data;
		[array addObject: value];
	} else {
		array = [NSMutableArray arrayWithObject:value];
		[mInternalData setObject:array forKey:key];
	}
}

- (void) removeValue: (id) value forKey: (NSString *) key
{
	id data = [[self internalData] objectForKey:key];
	NSMutableArray *array;
	if(data && [data isKindOfClass: [NSArray class]]) {
		array = (NSMutableArray *) data;
		[array removeObject: value];
	}
}

- (NSString *) description
{
	return [mInternalData description];
}

- (void)dealloc
{
    [mInternalData release];
    [super dealloc];
}

@end
